/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fjnu.dao.mysql;

import java.sql.SQLException;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author neco
 */
public class MysqlConnectionPool {

    private Hashtable<Integer, MysqlConnection> Pool;
    private final static int minConnCount = 10;
    private final static int maxConCount = 100;
    private static MysqlConnectionPool sweetPool;
    private final static long maxWaitTime = 3000;
    private int workingConn;
    //private final static int maxInitTryCount=5;

    private MysqlConnectionPool() {

        workingConn = 0;
        Pool = new Hashtable<Integer, MysqlConnection>();
        for (int i = 0; i <= minConnCount; i++) {
            MysqlConnection conn = initConn();
            Pool.put(conn.hashCode(), conn);
        }
    }

    public int getMinConnCount() {
        return minConnCount;
    }

    public int getWorkingConnCount() {
        return workingConn;
    }

    public static MysqlConnectionPool getInstance() {
        init();
        return sweetPool;
    }

    private static synchronized void init() {
        if (sweetPool == null) {
            sweetPool = new MysqlConnectionPool();
        }
    }

    private MysqlConnection initConn() {
        MysqlConnection conn = new MysqlConnection();
        conn.loadDriver();
        if (checkConn(conn)) {
            return conn;
        } else {
            return null;
        }
    }

    public MysqlConnection getConn() {
        MysqlConnection conn = null;
        if (this.workingConn>= maxConCount) {
            try {
             Thread.sleep(maxWaitTime);
              if (this.workingConn > maxConCount) 
              {
                    throw new Exception();
                   
              }
            } catch (Exception ex) {
                Logger.getLogger(MysqlConnectionPool.class.getName()).log(Level.SEVERE, null, ex);
            }
             return conn;
        } else if (this.workingConn == Pool.size()) {
            conn = initConn();
        } else {
            conn = findFreeConn();
        }
        if(conn!=null)
        this.workingConn++;
        return conn;
    }

    public void freeConn(MysqlConnection conn) {
    
        conn.setFree();
        this.workingConn--;
    }

    private MysqlConnection findFreeConn() {
        java.util.Enumeration<MysqlConnection> poolEum = Pool.elements();
        MysqlConnection conn = null;
        while (poolEum.hasMoreElements()) {

            MysqlConnection temp = poolEum.nextElement();
            if (temp.isBusy())
                        ; else if (checkConn(temp)) {
                conn = temp;
            }        }
        return conn;
    }

    private boolean checkConn(MysqlConnection conn) {
        if (conn == null) {
            return false;
        } else {
            try {
                if (conn.isClosed()) {
                    Pool.remove(conn.hashCode());
                    if (Pool.size() < this.minConnCount) {
                        MysqlConnection conn2 = new MysqlConnection();
                        conn2.loadDriver();
                        Pool.put(conn2.hashCode(), conn2);
                    }
                }
                return !conn.isClosed();
            } catch (SQLException ex) {
                Logger.getLogger(MysqlConnectionPool.class.getName()).log(Level.SEVERE, null, ex);
                return false;
            }
        }
    }
}
